package com.fcbox.conf;

import com.fcbox.prop.RedisProperties;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisPoolConfig;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

/**
 * 多redis配置
 * Created by 000498 on 2016/11/30.
 */
@Configuration
public class MultiRedisConfig {
	@Bean(name="edmsProperties")
	@ConfigurationProperties(prefix = "redis.edms")
	public RedisProperties edmsProperties(){
		return new RedisProperties();
	}

	@Bean(name="uicProperties")
	@ConfigurationProperties(prefix = "redis.uic")
	public RedisProperties uicProperties(){
		return new RedisProperties();
	}

	/**
	 * 这个是edms的redis
	 * 这里的名称取为redisTemplate是因为在没有名为redisTemplate的bean的时候spring boot会自动创建一个RedisTemplate
	 * 所以这里给他取名为redisTemplate
	 *
	 * 其实这个方法不写，也可以通过redisTemplate获取到，只是为了方便识别，所以才写出来
	 * @return
	 * @throws UnknownHostException
	 */
	@Bean(name = "redisTemplate")
	@Primary
	public RedisTemplate edmsRedisTemplate()
			throws UnknownHostException {
		RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
		template.setConnectionFactory(edmsRedisConnectionFactory());

		StringRedisSerializer keySerializer = new StringRedisSerializer();
		template.setKeySerializer(keySerializer);
		return template;
	}

	/**
	 * 这个方法跟上面那个方法一样，不写，spring boot也会自动创建这么一个bean
	 * 为了方便识别，才给他手动写出来
	 * @return
	 * @throws UnknownHostException
	 */
	@Bean
	public StringRedisTemplate stringRedisTemplate()
			throws UnknownHostException {
		StringRedisTemplate template = new StringRedisTemplate();
		template.setConnectionFactory(edmsRedisConnectionFactory());
		return template;
	}

	@Bean(name = "uicRedisTemplate")
	public RedisTemplate uicRedisTemplate()
			throws UnknownHostException {
		RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
		template.setConnectionFactory(uicRedisConnectionFactory());
		return template;
	}

	@Bean(name="edmsRedisConnectionFactory")
	@Primary
	public RedisConnectionFactory edmsRedisConnectionFactory(){
		RedisProperties redisProperties = edmsProperties();

		JedisPoolConfig poolConfig = new JedisPoolConfig();
		RedisProperties.Pool props = redisProperties.getPool();
		poolConfig.setMaxTotal(props.getMaxActive());
		poolConfig.setMaxIdle(props.getMaxIdle());
		poolConfig.setMinIdle(props.getMinIdle());
		poolConfig.setMaxWaitMillis(props.getMaxWait());

		RedisSentinelConfiguration sentinelConfiguration = new RedisSentinelConfiguration();
		sentinelConfiguration.master(redisProperties.getSentinel().getMaster());
		sentinelConfiguration.setSentinels(createSentinels(redisProperties.getSentinel()));

		JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(sentinelConfiguration, poolConfig);
		jedisConnectionFactory.setPassword(redisProperties.getPassword());
		return jedisConnectionFactory;
	}

	@Bean(name="uicRedisConnectionFactory")
	public RedisConnectionFactory uicRedisConnectionFactory(){
		RedisProperties redisProperties = uicProperties();

		JedisPoolConfig poolConfig = new JedisPoolConfig();
		RedisProperties.Pool props = redisProperties.getPool();
		poolConfig.setMaxTotal(props.getMaxActive());
		poolConfig.setMaxIdle(props.getMaxIdle());
		poolConfig.setMinIdle(props.getMinIdle());
		poolConfig.setMaxWaitMillis(props.getMaxWait());

		RedisSentinelConfiguration sentinelConfiguration = new RedisSentinelConfiguration();
		sentinelConfiguration.master(redisProperties.getSentinel().getMaster());
		sentinelConfiguration.setSentinels(createSentinels(redisProperties.getSentinel()));

		JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(sentinelConfiguration, poolConfig);
		jedisConnectionFactory.setPassword(redisProperties.getPassword());
		return jedisConnectionFactory;
	}

	private List<RedisNode> createSentinels(RedisProperties.Sentinel sentinel) {
		List<RedisNode> nodes = new ArrayList<RedisNode>();
		for (String node : StringUtils
				.commaDelimitedListToStringArray(sentinel.getNodes())) {
			try {
				String[] parts = StringUtils.split(node, ":");
				Assert.state(parts.length == 2, "Must be defined as 'host:port'");
				nodes.add(new RedisNode(parts[0], Integer.valueOf(parts[1])));
			}
			catch (RuntimeException ex) {
				throw new IllegalStateException(
						"Invalid redis sentinel " + "property '" + node + "'", ex);
			}
		}
		return nodes;
	}
}
